#ifndef CQ_GUARD_H
#define CQ_GUARD_H

#include "CQ_defines.h"
#include <atomic>

DEFINE_NAMESPACE_CQ_BEGIN
class CQGuard
{
public:
	CQGuard()
		: m_guard(new CQGuardHelper)
		, m_isHost(true)
	{
	}

	~CQGuard()
	{
		if (m_isHost) {
			*m_guard->m_vaild = false;
		}

		if ((--(*m_guard->m_ref)) == 0) {
			delete m_guard;
		}
	}

	CQGuard(const CQGuard& other)
	{
		m_guard = other.m_guard;
		m_isHost = false;
		++(*m_guard->m_ref);
	}

	CQGuard& operator=(const CQGuard& other)
	{
		m_guard = other.m_guard;
		m_isHost = false;
		++(*m_guard->m_ref);
		return *this;
	}

	operator bool()
	{
		return m_guard->m_vaild;
	}

private:
	struct CQGuardHelper
	{
		CQGuardHelper()
		{
			m_ref = new std::atomic_int(1);
			m_vaild = new std::atomic_bool(true);
		}

		~CQGuardHelper()
		{
			delete m_ref;
			delete m_vaild;
		}
		std::atomic_int* m_ref;
		std::atomic_bool* m_vaild;
	};

	CQGuardHelper* m_guard;
	std::atomic_bool m_isHost;
};

template<typename T>
class CQGuardPtr
{
public:
	CQGuardPtr(T* ptr_)
		:m_ptr(ptr_)
		, m_guard(ptr_->guard())
	{
	}

	T* operator->()
	{
		return m_ptr;
	}

	T& operator*()
	{
		return *m_ptr;
	}

	operator bool()
	{
		return m_guard;
	}

private:
	T* m_ptr;
	CQGuard m_guard;
};

DEFINE_NAMESPACE_CQ_END

#endif // CQ_GUARD_H
